
using PolicyAlgebra.Util;

namespace PolicyAlgebra.Type
{
	///<summary>
	///    This class defines a set of permission sets. It is this 
	///    type of set that is associated with an objects to specify
	///    what permissions a role might have over an object.
	///</summary>
	public class PermissionSetSet : Set<PermissionSet>
	{ 
		///<summary>
		/// Constructor.
		///</summary>
		///<param name="perms">The permission sets (possibly none) that should be in the set upon construction</param>
		public PermissionSetSet(params PermissionSet[] perms) : base(perms) {}

		
		///<summary>
		/// Constructor.
		///</summary>
		///<param name="set">The set of permission sets that should be in the set upon construction</param>
		public PermissionSetSet(Set<PermissionSet> set) : base(set) {}


		///<summary>
		/// This method implements the inner conjunction as defined by the
		/// algebra. The parameters are used to generate a new set of
		/// permission sets, hence not altering the existing sets.
		///</summary>
		///<param name="s1">The first set in the conjunction</param>
		///<param name="s2">The second set in the conjunction</param>
		///<remarks>
		/// This operation is implemented using conjuntion as it is implemented
		/// in the Set class.
		///</remarks>
		public static PermissionSetSet InnerConjunction(PermissionSetSet s1, PermissionSetSet s2)
		{
			PermissionSetSet newSetSet;
			newSetSet = new PermissionSetSet(PermissionSetSet.Conjunction(s1,s2));
			return newSetSet;
		}


		///<summary>
		/// This method implements the inner disjunction as defined by the
		/// algebra. The parameters are used to generate a new set of
		/// permission sets, hence not altering the existing sets.
		///</summary>
		///<param name="s1">The first set in the disjunction</param>
		///<param name="s2">The second set in the disjunction</param>
		///<remarks>
		/// This operation is implemented using disjuntion as it is implemented
		/// in the Set class.
		///</remarks>
		public static PermissionSetSet InnerDisjunction(PermissionSetSet s1, PermissionSetSet s2)
		{
			PermissionSetSet newSetSet;
			newSetSet = new PermissionSetSet(PermissionSetSet.Disjunction(s1,s2));
			return newSetSet;
		}


		//
		// Below follows the methods that are used to compare two of these sets.


		///<summary>
		/// This operator checks two sets for equality.
		///</summary>
		///<param name="s1">The first set in the comparison</param>
		///<param name="s2">The second set in the comparison</param>
		public static bool operator ==(PermissionSetSet s1, PermissionSetSet s2)
		{
			return s1.Equals(s2);
		}


		///<summary>
		/// This operator checks two sets for inequality.
		///</summary>
		///<param name="s1">The first set in the comparison</param>
		///<param name="s2">The second set in the comparison</param>
		public static bool operator !=(PermissionSetSet s1, PermissionSetSet s2)
		{
			return !(s1.Equals(s2));
		}


		///<summary>
		/// This method checks two sets for equality (the instance that the
		/// method is called upon and the supplied one).
		///</summary>
		///<param name="s1">The supplied set for comparison</param>
		public override bool Equals(object s1)
		{
			if (! (s1 is PermissionSetSet))
			{
				return false;
			}

			foreach (PermissionSet m in (PermissionSetSet) s1)
			{
				if (! this.IsMember(m))
				{
					return false;
				}
			}

			return true;
		}


		///<summary>
		/// Compute a hashcode for an object of this type.
		///</summary>
		///<returns>Integer hashcode</returns>
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

	}
}
